﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using UnityEngine;

class SocketClient
{
    string ip = "192.168.11.22";
    int port = 8500;
    NetworkStream stream;
    TcpClient client;
    const int BufferSize = 8192;
    byte[] buffer = new byte[BufferSize];

    MemoryStream mem;//缓存流
    BinaryReader reader;//缓存流的读取器
    public SocketClient()
    {
        client = new TcpClient();
        client.BeginConnect(ip, port, OnConnet, null);
    }
    private void OnConnet(IAsyncResult ar)
    {
        Debug.Log("已连接服务器" + client.Client.RemoteEndPoint);
        stream = client.GetStream();//获取网络流
        mem = new MemoryStream();
        reader = new BinaryReader(mem);
        //开启异步读取数据
        stream.BeginRead(buffer, 0, BufferSize, Read, null);
    }
    //子线程读取消息
    private void Read(IAsyncResult ar)
    {
        try
        {
            int readCount = stream.EndRead(ar);
            if (readCount == 0) throw new Exception("读取异常");
            //接收一次，把消息抛给逻辑层
            OnReceive(buffer, readCount);
            lock (client)
            {
                Array.Clear(buffer, 0, BufferSize);
                stream.BeginRead(buffer, 0, BufferSize, Read, null);
            }
        }
        catch (Exception e)
        {
            Debug.Log("Exception:" + e.ToString());
            OnDisconnect();
        }
    }
    //逻辑层 解包 处理[长度+消息] 
    void OnReceive(byte[] bytes, int count)
    {
        mem.Seek(0, SeekOrigin.End);//指针指到最后
        mem.Write(bytes, 0, count);//消息往后追加
        mem.Seek(0, SeekOrigin.Begin);//指针指到开头
        while (RemaindLength() > 4)//判断剩余长度是否够一个int32的长度
        {
            //获取消息长度 指针后移4位
            int length = reader.ReadInt32();
            if (RemaindLength() >= length)//剩余字节数是否大于消息长度
            {
                byte[] content = reader.ReadBytes(length);
                OnMessage(content);
            }
            else
            {
                mem.Seek(-4, SeekOrigin.Current);//把指针前移四位 保证消息的完整性
                break;
            }
            byte[] remain = reader.ReadBytes(RemaindLength());//把剩余的半包读取出来
            mem.SetLength(0);//清除缓存流
            mem.Write(remain, 0, remain.Length);//写入剩余的半包
        }
    }
    //获取剩余字节长度
    int RemaindLength()
    {
        return (int)(mem.Length - mem.Position);
    }
    //接到一条消息[type+content]
    void OnMessage(byte[] content)
    {
        NetworkManager.Instance.AddEvent(new ByteBuffer(content));
    }
    //客户端断开链接
    void OnDisconnect()
    {
        stream.Close();//流关闭
        client.Close();//客户端关闭
    }
    //往流里面写入[长度+消息]
    void OnWrite(byte[] content)
    {
        try
        {
            ByteBuffer bytebuff = new ByteBuffer();
            bytebuff.WriteInt(content.Length); //获取内容和内容长度
            bytebuff.WriteBytes(content);

            //把最终消息发送出去
            byte[] bytes = bytebuff.ToBytes();
            stream.Write(bytes, 0, bytes.Length);
        }
        catch (Exception)
        {
            Debug.Log("与服务器断开连接");
            throw;
        }
    }
    //向服务器发送消息
    public void Send(byte type, string msg)
    {    
        ByteBuffer buf = new ByteBuffer();
        buf.WriteByte(type);
        buf.WriteString(msg);
        OnWrite(buf.ToBytes());
    }
    public void Send(byte type,byte[] content)
    {
        ByteBuffer buf = new ByteBuffer();
        buf.WriteByte(type);
        buf.WriteBytes(content);
        OnWrite(buf.ToBytes());
    }
}

